package com.ch.engine.utils.aes1;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

public class AesUtils {

    // 生成密钥
    public static SecretKeySpec generateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
        //todo 可以放配置文件内
        byte[] keyBytes = hexStringToByteArray("888762A983741DBC8D05B34EF501A7E8");
        return new SecretKeySpec(keyBytes, "AES");
    }

    // 加密
    public static byte[] encrypt(String plaintext, SecretKey key, byte[] iv) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
        byte[] cipherText = cipher.doFinal(plaintext.getBytes());
        return cipherText;
    }

    // 解密
    public static String decrypt(byte[] cipherText, SecretKey key, byte[] iv) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
        byte[] plainText = cipher.doFinal(cipherText);
        return new String(plainText);
    }

    // 将十六进制字符串转换为字节数组
    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }

    // 生成随机的初始化向量（IV）
    public static byte[] generateIV() throws NoSuchAlgorithmException {
        SecureRandom random = SecureRandom.getInstanceStrong();
        byte[] iv = new byte[16];
        random.nextBytes(iv);
        return iv;
    }

    // 生成固定内容的初始化盐（IV）
    public static byte[] generateIVFixation() {
        //todo 可以放配置文件内
        byte[] fixedIV = hexStringToByteArray("0DE102F8524666EDB3628FF31F11B465");
        return fixedIV;
    }


    // 将字节数组转换为十六进制字符串
    public static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02X", b));
        }
        return result.toString();
    }

    public static String getData(String val, String symbol, int subscript) {
        String[] vals = val.split(symbol);
        return vals[subscript];
    }

    public static void main(String[] args) {
        try {
            String plaintext = "1wb0DxxxStt2a_Aw5DWCctcxxxMZWSudn," +
                    "mwXbbmGidUCpxxxPRr25_WGq5GX0l9RA7xxxh5xW," +
                    "5WGBQqYXxxxXZc8WmAJ_FoLlEufCxxxyUOZZee5m," +
                    "WyYXbkFxxxIMj9DQt1rr_NVwLh38GDTHTxxx5wF," +
                    "B7SZsY8xxx00ip6KVB_C3Nex8GuOfqBxxxKNkW";
            System.out.println("原始: " + plaintext);
            //盐
            byte[] iv = generateIVFixation();
            // 生成密钥
            SecretKeySpec keySpec = generateKey();
            // 加密
            byte[] cipherText = encrypt(plaintext, keySpec, iv);
            System.out.println("加密: " + bytesToHex(cipherText));
            // 解密
            String decryptedText = decrypt(hexStringToByteArray(bytesToHex(cipherText)), keySpec, iv);
            System.out.println("解密: " + decryptedText);
            System.out.println(getData(decryptedText, ",", 0));
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException |
                 InvalidKeyException | BadPaddingException | IllegalBlockSizeException | InvalidKeySpecException e) {
            e.printStackTrace();
        }
    }
}